#include "stdafx.h"
#include <time.h>

namespace hc
{
	const _value_t CException::get_value( const string& name ) const
	{
		map<string,_value_t,less_no_case>::const_iterator ci = _values.find( name );

		if( ci == _values.end() )
			return _value_t();
		else
			return ci->second;
	}

	void CException::put_value( const string& name, const _value_t value )
	{
		map<string,_value_t,less_no_case>::iterator ci = _values.find( name );

		if( ci == _values.end() )
		{
			_values[name] = value;
			_values_order.push_back( name );
		} else
		{
			ci->second = value;
		}
	}

	void CException::clear_values()
	{
		_values.clear();
		_values_order.clear();
	}

	const _value_t CException::operator []( const string& name ) const
	{
		return get_value( name );
	}

	_value_t& CException::operator []( const string& name )
	{
		map<string,_value_t,less_no_case>::iterator i = _values.find( name );

		if( i == _values.end() )
		{
			i = _values.insert( pair<string,_value_t>( name, _value_t() ) ).first;
			_values_order.push_back( name );
		}
		return i->second;
	}

	const map<string,_value_t,less_no_case>& CException::values() const
	{
		return _values;
	}

	const list<string>& CException::values_order() const
	{
		return _values_order;
	}

	CException::CException()
	{
	}

	CException::CException( const void* iDummy )
	{
	}

	CException::CException( const pair<string,_value_t>& iValue1 )
	{
		_values_order.push_back( _values.insert( iValue1 ).first->first );
	}

	CException::CException( const pair<string,_value_t>& iValue1, const pair<string,_value_t>& iValue2 )
	{
		_values_order.push_back( _values.insert( iValue1 ).first->first );
		_values_order.push_back( _values.insert( iValue2 ).first->first );
	}

	CException::CException( const pair<string,_value_t>& iValue1, const pair<string,_value_t>& iValue2, const pair<string,_value_t>& iValue3 )
	{
		_values_order.push_back( _values.insert( iValue1 ).first->first );
		_values_order.push_back( _values.insert( iValue2 ).first->first );
		_values_order.push_back( _values.insert( iValue3 ).first->first );
	}

	CException::CException( const pair<string,_value_t>& iValue1, const pair<string,_value_t>& iValue2, const pair<string,_value_t>& iValue3, const pair<string,_value_t>& iValue4 )
	{
		_values_order.push_back( _values.insert( iValue1 ).first->first );
		_values_order.push_back( _values.insert( iValue2 ).first->first );
		_values_order.push_back( _values.insert( iValue3 ).first->first );
		_values_order.push_back( _values.insert( iValue4 ).first->first );
	}

	CException::CException( const pair<string,_value_t>& iValue1, const pair<string,_value_t>& iValue2, const pair<string,_value_t>& iValue3, const pair<string,_value_t>& iValue4, const pair<string,_value_t>& iValue5 )
	{
		_values_order.push_back( _values.insert( iValue1 ).first->first );
		_values_order.push_back( _values.insert( iValue2 ).first->first );
		_values_order.push_back( _values.insert( iValue3 ).first->first );
		_values_order.push_back( _values.insert( iValue4 ).first->first );
		_values_order.push_back( _values.insert( iValue5 ).first->first );
	}

	CException::CException( const pair<string,_value_t>& iValue1, const pair<string,_value_t>& iValue2, const pair<string,_value_t>& iValue3, const pair<string,_value_t>& iValue4, const pair<string,_value_t>& iValue5, const pair<string,_value_t>& iValue6 )
	{
		_values_order.push_back( _values.insert( iValue1 ).first->first );
		_values_order.push_back( _values.insert( iValue2 ).first->first );
		_values_order.push_back( _values.insert( iValue3 ).first->first );
		_values_order.push_back( _values.insert( iValue4 ).first->first );
		_values_order.push_back( _values.insert( iValue5 ).first->first );
		_values_order.push_back( _values.insert( iValue6 ).first->first );
	}

	CException::CException( const CException& iException )
	{
		_values = iException._values;
		_values_order = iException._values_order;
	}

	CException::~CException() throw()
	{
	}

	void CException::move_to_back( const string& name )
	{
		map<string,_value_t,less_no_case>::iterator ci = _values.find( name );

		if( ci == _values.end() )
			return;
		_values_order.remove( name );
		_values_order.push_back( name );
	}

	string CException::get_info() const
	{
		static string										what;
		map<string,_value_t,less_no_case>::const_iterator	wi;
		list<string>::const_iterator						wi2;
		//TLock												wl( what_lock );

		wi = _values.find( "Text" );
		if( ( wi != _values.end() ) && ( _values.size() == 1 ) )
		{
			what = as_string(wi->second);
		} 
		else
		{
			what.clear();

			map<string,_value_t,less_no_case> tmp_vals = _values;
			for( wi2 = _values_order.begin(); wi2 != _values_order.end(); )
			{
				const string&	_name = *wi2;
				const _value_t	_value = tmp_vals[_name];
				tmp_vals.erase(_name);

				what.append( _name );
				what.append( ": " );
				what.append( as_string(_value) );
				++wi2;
				if( wi2 != _values_order.end() )
					what.append( "\n" );
			}

			if( !tmp_vals.empty() )
				what.append( "\n" );

			for( wi = tmp_vals.begin(); wi != tmp_vals.end(); )
			{
				what.append( wi->first );
				what.append( ": " );
				what.append( as_string(wi->second) );
				++wi;
				if( wi != tmp_vals.end() )
					what.append( "\n" );
			}
		}

		if( *what.rbegin() != '\n' )
			what.append( "\n" );

		return what;	
	}


	const char* CException::what() const throw()
	{
		//static TCriticalSection								what_lock;
		string what = get_info();

		if(!StackLayout.empty())		
		{
			what.append("StackLayout:\n");
		}
		for(list<string>::const_iterator LI=StackLayout.begin();LI!=StackLayout.end();LI++)
		{
			what.append(*LI);
			what.append("\n");
		}
	
		return what.c_str();
	}

	ENetworkException::ENetworkException( const pair<string,_value_t>& iValue1 )
	:CException(iValue1)
	{
	}

	ERuntimeException::ERuntimeException( int iCode )
	:CException( pair<string,_value_t>( "Code", iCode ) )
	{
		char* buf=strerror(iCode);
		_values["Text"]=string(buf);
	}

	ERuntimeException::ERuntimeException( int iCode, const pair<string,_value_t>& iValue1 )
	:CException( pair<string,_value_t>( "Code", iCode ),
			  iValue1 )
	{
		char* buf=strerror(iCode);
		_values["Text"]=string(buf);
	}

	ERuntimeException::ERuntimeException( int iCode, const pair<string,_value_t>& iValue1, const pair<string,_value_t>& iValue2 )
	:CException( pair<string,_value_t>( "Code", iCode ),
			  iValue1,
			  iValue2 )
	{
		char* buf=strerror(iCode);
		_values["Text"]=string(buf);
	}

	EBadCastException::EBadCastException( const type_info& iFromType, const type_info& iToType )
	:CException( pair<string,_value_t>( "Text", string("Bad cast") ),
			  pair<string,_value_t>( "From", iFromType.name() ),
			  pair<string,_value_t>( "To", iToType.name() ) )
	{
	}

	EBadCastException::EBadCastException( const type_info& iFromType, const type_info& iToType, const type_info& iRealType )
	:CException( pair<string,_value_t>( "Text", string("Bad cast") ),
			  pair<string,_value_t>( "From", iFromType.name() ),
			  pair<string,_value_t>( "To", iToType.name() ),
			  pair<string,_value_t>( "RealType", iRealType.name() ) )
	{
	}

};